/*
 * code.cpp
 *
 *  Created on: Jan 14, 2014
 *      Author: killerg
 */

#include "bill_deps.h"
#include "code.h"
#include "bill.h"
#include "bill_console.h"

#include "share/db_mgr.h"
#include "share/util.h"
#include "share/clock.h"

bool code_t::reload_code() {
	all_code.clear();

    std::string cfg_path = fmt_cstr("%s/cfg/code.txt", get_deploy());
    Json::Value cfg;
    const char* cfg_file = load_file(cfg_path.c_str());
    if (NULL != cfg_file)
        cfg = to_json(cfg_file);

    const Json::Value &codes = cfg["item"];
    if (!codes.isArray()) {
        UTIL_LOG(E, "code file empty");
        return false;
    }

    for (auto itr = codes.begin(); itr != codes.end(); ++itr) {
        std::string code = (*itr).get("code", "").asCString();
        all_code.insert(code);
    }

    return true;
}

bool code_t::init() {
	if (!reload_code())
		return false;

    bool ret = g_bill.db->get(
            "_code",
            [this, &ret](db_error_t err, const Json::Value &value){
                switch (err) {
                case DBE_Success: {
                    const Json::Value &codes = value["used"];
                    for (auto itr = codes.begin(); itr != codes.end(); ++itr) {
                    	auto code = (*itr).asCString();
                    	if (all_code.count(code) > 0)
                    		used_code.insert(code);
                    }
                    ret = true;
                }break;
                case DBE_NoExist:
                    ret = true;
                    break;
                default:
                    ret = false;
                    break;
                }
            });

    if (!ret) {
        UTIL_LOG(E, "used code load error");
        return false;
    }

    g_bill.db->wait();

    chged = false;
    save_timer = 10.0f;

    g_console->watch_n("used_code", [this]()->int32_t{ return used_code.size(); }, [this](){return all_code.size();});

    return true;
}

void code_t::destroy() {
    all_code.clear();
    used_code.clear();
}

void code_t::update() {
    save_timer -= g_bill.clock->delta;
    if (chged && save_timer <= 0.0f) {
        save_timer = 10.0f;

        Json::Value value;
        Json::Value &used = value["used"];
        for (const auto &code : used_code)
            used.append(code);

        chged = !g_bill.db->set(
                "_code",
                value,
                [this](db_error_t err){
                    switch (err) {
                    case DBE_Success:
                        break;
                    default:
                        chged = false;
                        UTIL_LOG(E, "_code save err");
                        break;
                    }
                });
    }
}
